﻿
using Dora.Tools.Utility.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dora.Tools.Utility.Const;
using Dora.Tools.Enums;

namespace Dora.Tools.Utility.Redis
{
    /// <summary>
    /// token信息说明
    /// userId加DoraRedisKey.WebPre前缀为webtoken值，DoraRedisKey.UserInfoPre前缀为IdentityUserDto实体json序列化的信息，加DoraRedisKey.AuthKeyPre前缀为aukeys}
    /// 
    /// </summary>
    public class TokenHelper
    {
        /// <summary>
        /// 保存token的时候把IdentityUserDto一并写入redis
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="token"></param>
        /// <param name="user"></param>
        /// <param name="timeSpan"></param>
        /// <returns></returns>
        public static async Task SaveTokenAsync(string userId, string token, IdentityUserDto user)
        {
            TimeSpan timeSpan = GetTimeSpanBySystem(user.SystemKey);

            var seconds = (int)timeSpan.TotalMilliseconds;
            //写web_token  前缀

            await Task.Run(() =>
            {
                 RedisManager.SetAsync(string.Concat(DoraRedisKey.WebPre, userId), token, seconds);
                //RedisManager.Expire(string.Concat(DoraRedisKey.AuthKeyPre, userId), timeSpan);
                 RedisManager.SetAsync(string.Concat(DoraRedisKey.UserInfoPre, userId), user.SerializeToJson(), seconds); //userinfo
            });

        }

        /// <summary>
        /// 更新UserInfo
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="token"></param>
        /// <param name="user"></param>
        /// <param name="timeSpan"></param>
        /// <returns></returns>
        public static async Task UpdateUserInfoAsync(string userId, IdentityUserDto user)
        {
            TimeSpan timeSpan = GetTimeSpanBySystem(user.SystemKey);

            var seconds = (int)timeSpan.TotalMilliseconds;
            await RedisManager.SetAsync(string.Concat(DoraRedisKey.UserInfoPre, userId), user.SerializeToJson(), seconds); //userinfo
        }

        private static TimeSpan GetTimeSpanBySystem(string systemKey)
        {
            TimeSpan timeSpan;
            if (systemKey == DoraSysIdentifier.TasMP.ToDescription())
            {
                timeSpan = AppConfig.AccessTokenExpireTimeSpanMP;
            }
            else
            {
                timeSpan = AppConfig.AccessTokenExpireTimeSpan;
            }
            return timeSpan;
        }

        /// <summary>
        /// 根据userid获取IdentityUserDto
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public static async Task<IdentityUserDto> GetIdentityUserDtoAsync(string userId)
        {
            return await RedisManager.GetAsync<IdentityUserDto>(string.Concat(DoraRedisKey.UserInfoPre, userId));
        }

        /// <summary>
        /// 【同步】根据userid获取IdentityUserDto
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public static IdentityUserDto GetIdentityUserDto(string userId)
        {
            return RedisManager.Get<IdentityUserDto>(string.Concat(DoraRedisKey.UserInfoPre, userId));
        }
        /// <summary>
        /// 根据userId获取token
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public static async Task<string> GetTokenAsync(string userId)
        {
            return await RedisManager.GetAsync<string>(string.Concat(DoraRedisKey.WebPre, userId));
        }
        /// <summary>
        /// 设置某个用户的auth-key
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="aukeyList"></param>
        /// <returns></returns>
        public static async Task<bool> SetAuthKeyAsync(string userId, List<AuthKeyItem> aukeyList)
        {

            var userDto =await GetIdentityUserDtoAsync(userId);

            if (userDto == null)
            {
                _ = InvalidTokenAsync(userId);
                return false;
            }
            userDto.AuthKeyList = aukeyList;

            TimeSpan timeSpan = GetTimeSpanBySystem(userDto.SystemKey);
            var seconds = (int)timeSpan.TotalMilliseconds;
            await RedisManager.SetAsync(string.Concat(DoraRedisKey.UserInfoPre, userId), userDto.SerializeToJson(), seconds);
            return true;

        }

        /// <summary>
        /// 设置某个用户的auth-key
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="aukeyList"></param>
        /// <returns></returns>
        public static async Task<bool> SetIdentityUserAsync(string userId,IdentityUserDto userDto)
        {
            TimeSpan timeSpan = GetTimeSpanBySystem(userDto.SystemKey);
            var seconds = (int)timeSpan.TotalMilliseconds;
            return await RedisManager.SetAsync(string.Concat(DoraRedisKey.UserInfoPre, userId), userDto.SerializeToJson(), seconds);
        }

        /// <summary>
        /// 刷新token
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="timeSpan"></param>
        /// <returns></returns>
        public static async Task ReFreshTokenAsync(string userId, TimeSpan timeSpan)
        {
            await Task.Run(() =>
            {
                RedisManager.ExpireAsync(string.Concat(DoraRedisKey.WebPre, userId), timeSpan);
                RedisManager.ExpireAsync(string.Concat(DoraRedisKey.UserInfoPre, userId), timeSpan);
              
            });
        }
        /// <summary>
        ///  注销token
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public static async Task InvalidTokenAsync(string userId)
        {
            //await ReFreshTokenAsync(userId, TimeSpan.Zero);
            await Task.Run(() =>
              {
                  RedisManager.DelAsync(string.Concat(DoraRedisKey.WebPre, userId));
                  RedisManager.DelAsync(string.Concat(DoraRedisKey.UserInfoPre, userId));
              });
        }

        /// <summary>
        /// 读auth-key
        /// </summary>
        /// <returns></returns>
        public static async Task<List<AuthKeyItem>> GetAuthKeyAsync(string userId)
        {
            var userdto = await GetIdentityUserDtoAsync(userId);
            return userdto.AuthKeyList;
            //return await RedisManager.GetAsync<string>(string.Concat(DoraRedisKey.AuthKeyPre, userId));
        }

        /// <summary>
        /// 用token换用户信息,如返回为空，注销token
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task<IdentityUserDto> Token2UserInfoAsync(string token)
        {
            if (string.IsNullOrWhiteSpace(token))
            { return null; }
            var jwtToken = token.Split('.');
            if (jwtToken.Length != 3) return null;
            var userId = await TokenPart2UserIdAsync(jwtToken[1]);
            var user = await GetIdentityUserDtoAsync(userId);
            return user;
        }

        /// <summary>
        /// 【同步】用token换用户信息,如返回为空，注销token
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static IdentityUserDto Token2UserInfo(string token)
        {
            if (string.IsNullOrWhiteSpace(token))
            { return null; }
            var jwtToken = token.Split('.');
            if (jwtToken.Length != 3) return null;
            var userId = TokenPart2UserId(jwtToken[1]);
            var user = GetIdentityUserDto(userId);
            return user;
        }


        /// <summary>
        /// token中的第二部分转换为userId
        /// </summary>
        /// <param name="tokenPart2"> token中的第二部分</param>
        /// <returns>userId</returns>
        public static async Task<string> TokenPart2UserIdAsync(string tokenPart2)
        {
            var userId = Encoding.UTF8.GetString(Convert.FromBase64String(tokenPart2));
            return await Task.FromResult(userId);
        }
        /// <summary>
        /// 【同步】token中的第二部分转换为userId
        /// </summary>
        /// <param name="tokenPart2"> token中的第二部分</param>
        /// <returns>userId</returns>
        public static string TokenPart2UserId(string tokenPart2)
        {
            var userId = Encoding.UTF8.GetString(Convert.FromBase64String(tokenPart2));
            return userId;
        }
        /// <summary>
        /// token转userId
        /// </summary>
        /// <param name="token">token</param>
        /// <returns>userId</returns>
        public static async Task<string> Token2UserIdAsync(string token)
        {
            if (string.IsNullOrWhiteSpace(token))   return null;
            var jwtToken = token.Split('.');
            return jwtToken.Length != 3 ? null : await TokenPart2UserIdAsync(jwtToken[1]);
        }
        /// <summary>
        /// token转userId【同步】
        /// </summary>
        /// <param name="token">token</param>
        /// <returns>userId</returns>
        public static string Token2UserId(string token)
        {
            if (string.IsNullOrWhiteSpace(token)) return null;
            var jwtToken = token.Split('.');
            return jwtToken.Length != 3 ? null : TokenPart2UserId(jwtToken[1]);
        }

        public static async Task<string> Token2DateTimeAsync(string token)
        {
            return await Task.FromResult(Encoding.UTF8.GetString(Convert.FromBase64String(token.Split(".")[0])));
        }



    }
}
